﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Data;
using System.Xml;
using SPErrorHandler;
using SendMail;
using System.Configuration;
using System.Collections;

namespace SPWarmUp
{
    class WarmUp
    {
        #region Get AppSettings
        string toMail = ConfigurationManager.AppSettings["ToMail"];
        string fromMail = ConfigurationManager.AppSettings["FromMail"];
        string warmUpLogFile = ConfigurationManager.AppSettings["WarmUpLogFile"];
        string smtpServer = ConfigurationManager.AppSettings["SmtpServer"];
        #endregion
        public ArrayList excludeArrayList = new ArrayList();

        public void WarmUpUrl()
        {
            DeleteFile(warmUpLogFile);
            FillExcludeArrayList();
            List<SPWebApplication> webApps = GetSharePointWebApps();
            List<SPWeb> subSites = GetSharePointSubSites();
            if (webApps != null || subSites != null)
            {
                if (string.IsNullOrEmpty(ConfigurationManager.AppSettings["UpdateHostFile"])) {}
                else
                {
                    string updateHostFile = ConfigurationManager.AppSettings["UpdateHostFile"].ToString();
                    if (updateHostFile == "1")
                    {
                        //Get the system root folder windows(Equivalent to %SystemRoot%)  
                        string windowsPath = System.Environment.GetEnvironmentVariable("windir");
                        DeleteFile(windowsPath + @"\system32\drivers\etc\hosts");
                        WriteDefaultHostsFileInfo();
                        UpdateHostsFile(webApps);
                    }
                }           
                GetSPWebUrl(subSites);
                //Send manual WarmUp
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue1"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue1"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue2"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue2"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue3"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue3"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue4"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue4"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue5"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue5"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue6"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue6"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue7"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue7"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue8"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue8"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue9"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue9"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["WarmUpValue10"])) { SendHttpWebRequest(ConfigurationManager.AppSettings["WarmUpValue10"]); };

                if (ConfigurationManager.AppSettings["MailNotifications"] == "1")
                {
                    //Send mail with WarmUp Log if an error occured
                    if (File.Exists(warmUpLogFile))
                    {
                        //Send WarmUp Log via E-Mail
                        SendEMail SendMessage = new SendEMail();
                        SendMessage.SendMailMessage("WarmUP Log", "WarmUp Log - " + GetHostName(), fromMail, toMail, smtpServer, warmUpLogFile);
                    }
                }
            }
            else
            {
                if (ConfigurationManager.AppSettings["MailNotifications"] == "1")
                {
                    //Send mail with WarmUp Log if an error occured
                    if (File.Exists(warmUpLogFile))
                    {
                        //Send WarmUp Log via E-Mail
                        SendEMail SendMessage = new SendEMail();
                        SendMessage.SendMailMessage("WarmUP Log", "WarmUp Log - " + GetHostName(), fromMail, toMail, smtpServer, warmUpLogFile);
                    }
                }
            }
        }

        public void FillExcludeArrayList()
        {
            try
            {
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue1"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue1"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue2"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue2"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue3"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue3"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue4"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue4"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue5"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue5"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue6"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue6"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue7"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue7"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue8"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue8"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue9"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue9"]); };
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["ExcludeWarmUpValue10"])) { excludeArrayList.Add(ConfigurationManager.AppSettings["ExcludeWarmUpValue10"]); };
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace.ToString());
            }
         }

        private static void WriteDefaultHostsFileInfo()
        {
            string windowsPath = System.Environment.GetEnvironmentVariable("windir");
            using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(windowsPath + @"\system32\drivers\etc\hosts", true))
            {
                streamWriter.WriteLine("# This is a HOSTS file used by WarmUp tool");
                streamWriter.WriteLine("# Created: " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
                streamWriter.Close();
            } 
        }

        private static List<SPWebApplication> GetSharePointWebApps()
        {
            try
            {
                string url = string.Empty;
                string webAppName = string.Empty;
                List<SPWebApplication> webApps = new List<SPWebApplication>();
                SPServiceCollection myService = SPFarm.Local.Services;
                foreach (SPService sps in myService)
                {
                    webAppName = sps.DisplayName.ToString();
                    try
                    {
                        if (sps is SPWebService)
                        {
                            SPWebService spws = (SPWebService)sps;
                            foreach (SPWebApplication spwebapp in spws.WebApplications)
                            {
                                string str1 = spwebapp.Name.ToString();
                                url = GetUrlsStringForWebApp(spwebapp);
                                webApps.Add(spwebapp);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ErrorHandler errHandler = new ErrorHandler();
                        errHandler.WriteLogToFile("--------------------------------------------------------------");
                        errHandler.WriteLogToFile("Web Application Name: " + webAppName + "; URL: " + url + "; Time: " + DateTime.Now.ToLongTimeString());
                        errHandler.WriteLogToFile("Exception: " + ex.Message.ToString());
                        errHandler.WriteLogToFile("--------------------------------------------------------------");
                    }
                }
                return webApps;
            }
            catch (Exception ex)
            {
                ErrorHandler errHandler = new ErrorHandler();
                errHandler.WriteLogToFile("--------------------------------------------------------------");
                errHandler.WriteLogToFile("An error is occured during creating the List<SPWebApplication>! Check the availability of SQL/IIS Server!" + " Time: " + DateTime.Now.ToLongTimeString());
                errHandler.WriteLogToFile(ex.ToString());
                errHandler.WriteLogToFile("--------------------------------------------------------------");
                return null;
            }
        }

        private static List<SPWeb> GetSharePointSubSites()
        {
            try
            {
                string url = string.Empty;
                string webAppName = string.Empty;
                string webAppUrl = string.Empty;
                List<SPWeb> subSites = new List<SPWeb>();
                foreach (SPWebApplication webApp in SPWebService.ContentService.WebApplications)
                {
                    webAppName = webApp.DisplayName.ToString();
                    try
                    {
                        foreach (SPSite site in webApp.Sites)
                        {
                            foreach (SPWeb web in site.AllWebs)
                            {
                                url = web.Url.ToString();
                                subSites.Add(web);
                                url = string.Empty;
                                web.Dispose();
                            }
                        }
                    }
                    catch (Exception ex)
                    {                       
                        ErrorHandler errHandler = new ErrorHandler();
                        errHandler.WriteLogToFile("--------------------------------------------------------------");
                        errHandler.WriteLogToFile("Web Application Name: " + webAppName + "; URL: " + url + "; Time: " + DateTime.Now.ToLongTimeString());
                        errHandler.WriteLogToFile("Exception: " + ex.Message.ToString());
                        errHandler.WriteLogToFile("--------------------------------------------------------------");
                    }
                    finally
                    {
                        
                    }
                }
                return subSites;
            }
            catch (Exception ex)
            {
                ErrorHandler errHandler = new ErrorHandler();
                errHandler.WriteLogToFile("--------------------------------------------------------------");
                errHandler.WriteLogToFile("An error is occured during creating the List<SPWeb>! Check the availability of SQL/IIS Server!" + " Time: " + DateTime.Now.ToLongTimeString());
                errHandler.WriteLogToFile(ex.ToString());
                errHandler.WriteLogToFile("--------------------------------------------------------------");
                return null;
            }                
        }

        private static string GetUrlsStringForWebApp(SPWebApplication webApp)
        {
            try
            {
                string urls = string.Empty;
                foreach (SPAlternateUrl url in webApp.AlternateUrls)
                {
                    urls = urls + url.Uri + ",";
                }
                if (urls.EndsWith(","))
                    urls = urls.Substring(0, urls.Length - 1);
                if (urls.EndsWith("/"))
                    urls = urls.Substring(0, urls.Length - 1);
                return urls.ToLower();
            }
            catch (Exception ex)
            {
                ErrorHandler errHandler = new ErrorHandler();
                errHandler.WriteErrorToFile(ex.ToString());
                return "Error";
            }
            finally
            {
                //return "Error";
            }
        }

        private static string RemoveHttpPrefix(string url)
        {
            try
            {
                if (url.StartsWith("https://"))
                    url = url.Remove(0, 8);
                if (url.StartsWith("http://"))
                    url = url.Remove(0, 7);
                return url.ToLower();
            }
            catch (Exception ex)
            {
                ErrorHandler errHandler = new ErrorHandler();
                errHandler.WriteErrorToFile(ex.ToString());
                return "Error";
            }
            finally
            {
                //return "Error";
            }
        }

        private void SendHttpWebRequest(string url)
        {
            string errorUrl = url;
            //Set request timeout value
            int requestTimeoutValue = 200000;
            if (string.IsNullOrEmpty(ConfigurationManager.AppSettings["RequestTimeout"])) {}
            else
            {
                requestTimeoutValue = Convert.ToInt32(ConfigurationManager.AppSettings["RequestTimeout"]);
            }
            try
            {
                if (CheckExcludeList(url.ToLower()))
                {
                    //string url = GetUrlsStringForWebApp(webApp);
                    ErrorHandler errHandler = new ErrorHandler();
                    url.ToLower();
                    Console.WriteLine(url + " - Start Time: " + DateTime.Now);
                    //Write to Log File
                    //errHandler.WriteLogToFile(url + " StartTime: " + DateTime.Now.ToLongTimeString());
                    //Create a request for url
                    WebRequest request = WebRequest.Create(url);
                    request.Proxy = null;
                    request.Credentials = CredentialCache.DefaultCredentials;
                    request.Timeout = requestTimeoutValue;

                    //Get response
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                    //Read response status
                    Stream dataStream = response.GetResponseStream();
                    StreamReader reader = new StreamReader(dataStream);
                    string responseFromServer = reader.ReadToEnd();
                    //Write to Log File
                    //errHandler.WriteLogToFile(url + " EndTime: " + DateTime.Now.ToLongTimeString());
                    //errHandler.WriteLogToFile("--------------------------------------------------------------");
                    Console.WriteLine(url + " - End Time: " + DateTime.Now);
                }
            }
            catch (Exception ex)
            {
                ErrorHandler errHandler = new ErrorHandler();
                errHandler.WriteLogToFile("--------------------------------------------------------------");
                errHandler.WriteLogToFile(errorUrl + " Time: " + DateTime.Now.ToLongTimeString());
                errHandler.WriteLogToFile(ex.ToString());
                errHandler.WriteLogToFile("--------------------------------------------------------------");
            }
        }

        private void GetSPWebUrl(List<SPWeb> subSites)
        {
            foreach (SPWeb subSite in subSites)
            {
                SendHttpWebRequest(subSite.Url.ToString());
            }
        }

        public bool CheckExcludeList(string url)
        {
            bool notInList = true;
            foreach (string currentExcludeUrl in excludeArrayList)
                if (url.Contains(currentExcludeUrl.ToLower()))
                {
                    notInList = false;
                }
            return notInList;
        }

        private void UpdateHostsFile(List<SPWebApplication> webApps)
        {
            //Get the system root folder windows(Equivalent to %SystemRoot%)  
            string windowsPath = System.Environment.GetEnvironmentVariable("windir");
            //Get the host ip adresse
            string ipAdresse = GetHostIPAdresse();
            string url = string.Empty;
            foreach (SPWebApplication webApp in webApps)
            {
                try
                {
                    url = GetUrlsStringForWebApp(webApp);
                    url = RemoveHttpPrefix(url);
                    if (CheckExcludeList(url.ToLower()))
                    {
                        using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(windowsPath + @"\system32\drivers\etc\hosts", true))
                        {
                            streamWriter.WriteLine(ipAdresse + "       " + url);
                            streamWriter.Close();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }

        private void DeleteFile(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
            }
            catch (Exception ex)
            {
                ErrorHandler errHandler = new ErrorHandler();
                errHandler.WriteErrorToFile(ex.ToString());
            }
        }

        private string GetHostIPAdresse()
        {
            string HostName = System.Net.Dns.GetHostName();
            System.Net.IPHostEntry hostInfo = System.Net.Dns.GetHostEntry(HostName);
            string IpAdresse = hostInfo.AddressList[1].ToString();
            return IpAdresse;
        }

        private string GetHostName()
        {
            string HostName = System.Net.Dns.GetHostName();
            return HostName.ToUpper();
        }
    }   
}